/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.posplus.losspreventiondataimporter.importer;

import com.posplus.lossprevention.APDAOFactory;
import com.posplus.lossprevention.mapping.Cashiers;
import com.posplus.lossprevention.mapping.Registers;
import com.posplus.lossprevention.mapping.Stores;
import com.posplus.lossprevention.mapping.Transactions;
import com.posplus.losspreventiondataimporter.service.CashiersService;
import com.posplus.strack.mapping.RegisterHeader;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.posplus.losspreventiondataimporter.service.RegisterHeaderService;
import com.posplus.losspreventiondataimporter.service.RegistersService;
import com.posplus.losspreventiondataimporter.service.StoresService;
import com.posplus.losspreventiondataimporter.service.TransactionsService;
import com.posplus.losspreventiondataimporter.util.ListToMap;
import com.posplus.losspreventiondataimporter.util.Util;
import org.apache.log4j.Logger;

/**
 *
 * @author scottw
 */
public class RegisterHeaderImporter {

    private APDAOFactory lpFactory;
    private RegisterHeaderService registerHeaderService;
    private String storeCode;
    
    public RegisterHeaderImporter(RegisterHeaderService registerHeaderService, APDAOFactory lpFactory) {
        this.lpFactory = lpFactory;
        this.registerHeaderService = registerHeaderService;
    }

    public void dataImport(Calendar start, Calendar end) {
        logger.debug("Begin Data Import - Start: " + Util.toString(start) + " End: " + Util.toString(end));
        List<RegisterHeader> headers = registerHeaderService.getByDate(start, end);
        mapAndPersist(headers, lpFactory);
    }

    private void mapAndPersist(List<RegisterHeader> headers, APDAOFactory lpFactory) {
        List<Transactions> mappedTransactions = new ArrayList<Transactions>();
        StoresService storeService = new StoresService(lpFactory);
        Map<String, Stores> stores = ListToMap.storesToMap(storeService.getAll());

        try {
            Stores store = stores.get(storeCode);
            if (store == null) {
                throw new RuntimeException("Store " + storeCode + " not found");
            }

            Map<Integer, Registers> registers = ListToMap.registersToMap(store.getRegisterses());
            Map<String, Cashiers> cashiers = ListToMap.cashiersToMap(store.getCashierses());

            Iterator<RegisterHeader> iter = headers.iterator();
            while (iter.hasNext()) {
                RegisterHeader next = iter.next();

                try {
                    Cashiers cashier = cashiers.get(next.getId().getEmpNo().toString());
                    if (cashier == null) {
                        Logger.getRootLogger().debug("Cashier " + next.getId().getEmpNo() + " not found");
                        cashier = new Cashiers(store, next.getId().getEmpNo().toString(), "AUTOFILL", "AUTOFILL", "AUTOFILL", null, null, null);
                        Logger.getRootLogger().debug("Creating new Cashier: " + cashier);
                        CashiersService cashierService = new CashiersService(lpFactory);
                        cashierService.save(cashier);
                        cashiers.put(cashier.getCode(), cashier);
                    }

                    Registers register = registers.get(next.getId().getRegisterNo().intValue());
                    if (register == null) {
                        Logger.getRootLogger().debug("Register " + next.getId().getRegisterNo() + " not found");
                        register = new Registers(store, next.getId().getRegisterNo());
                        Logger.getRootLogger().debug("Creating new Register: " + register);
                        RegistersService registerService = new RegistersService(lpFactory);
                        registerService.save(register);
                        registers.put(register.getNumber(), register);
                    }

                    Calendar transactionEnd = next.getDatetime();
                    Calendar ringTimeStart = Calendar.getInstance();
                    BigDecimal endTimeInMillis = new BigDecimal(transactionEnd.getTimeInMillis());
                    BigDecimal ringTimeStartInMillis = endTimeInMillis.subtract(next.getTimeon());
                    ringTimeStart.setTimeInMillis(ringTimeStartInMillis.longValue());
                    Calendar ringTimeEnd = null;
                    if (next.getRingsPerMin().compareTo(new BigDecimal("0")) > 0) {
                        ringTimeEnd = estimateRingTimeEnd(ringTimeStart, next.getRingsPerMin(), next.getTotItems());
                    }

                    if (register != null && store != null && cashier != null && ringTimeStart != null
                            && ringTimeEnd != null && transactionEnd != null && next.getId().getTransNo() != null) {
                        Transactions trans = new Transactions(register, store, cashier, next.getProcDate().getTime(), ringTimeStart, ringTimeEnd, transactionEnd, next.getId().getTransNo());
                        mappedTransactions.add(trans);
                    }
                }catch(RuntimeException ex){
                    Logger.getLogger(RegisterTransImporter.class).warn(ex);
                }
            }
        } catch (RuntimeException ex) {
            Logger.getLogger(RegisterHeaderImporter.class).warn(ex);
        }

        if (mappedTransactions.size() > 0) {
            TransactionsService transactionsService = new TransactionsService(lpFactory);
            //transactionsService.bulkInsert(mappedTransactions);
	    transactionsService.saveAll(mappedTransactions);
        }
    }

    private static Calendar estimateRingTimeEnd(Calendar transactionStart, BigDecimal ringsPerMinute, BigDecimal numItems) {
        Calendar result = Calendar.getInstance();

        BigDecimal totalRingTime = numItems.divide(ringsPerMinute, 10, RoundingMode.HALF_UP).multiply(new BigDecimal("60"));

        result.setTimeInMillis(transactionStart.getTimeInMillis() + totalRingTime.longValue());

        return result;
    }

    public String getStoreCode() {
        return storeCode;
    }

    public void setStoreCode(String storeCode) {
        this.storeCode = storeCode;
    }
    
    private static final Logger logger = Logger.getLogger(RegisterHeaderImporter.class);
}
